﻿using ColiyerDependencyInject.Commom;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ColiyerLogger
{
    public class FileAppendObserver  
    {
        private readonly TokenHandler tokenhandle = new TokenHandler();
        private readonly ILog _log=ColiyerDependencyInject.InstanceProvider.Resolve<ILog>();
        private long _lastPosition;

        // Property for the file path to watch
        public string WatchPath { get; set; }

        // Event triggered when a new line is appended to the file
        public event Action<string> OnFileAppendNewLine;

        // Method to start monitoring the file
        public void Start()
        {
            if (string.IsNullOrEmpty(WatchPath) || !File.Exists(WatchPath))
            {
                throw new FileNotFoundException("File not found or path is empty.");
            }

            // Cancel any existing task if already watching
            Stop();

            var token=tokenhandle.CancelAndCreateNewToken();
            try
            {
                Task.Run(() => MonitorFileAsync(token), token);
            }
            catch (TaskCanceledException)
            {


            }
            catch (Exception ex)
            {
                _log.LogError(ex);
            }
        }

        // Method to monitor the file for new lines
        private async Task MonitorFileAsync(CancellationToken token)
        {
            using (var fileStream = new FileStream(WatchPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            using (var reader = new StreamReader(fileStream, Encoding.GetEncoding("GBK")??Encoding.Default))
            {
                try
                {

                    // Move to the last position of the file
                    fileStream.Seek(0, SeekOrigin.End);
                    _lastPosition = fileStream.Position;

                    while (!token.IsCancellationRequested)
                    {
                        fileStream.Seek(_lastPosition, SeekOrigin.Begin);

                        while (!reader.EndOfStream)
                        {
                            // Read the new lines that are added to the file
                            var newLine = await reader.ReadLineAsync();

                            // Trigger the event if a new line is found
                            OnFileAppendNewLine?.Invoke(newLine);
                        }

                        // Update the last known position
                        _lastPosition = fileStream.Position;

                        // Wait for a short period before checking again
                        await Task.Delay(100);
                    }
                }
                catch (ObjectDisposedException)
                {

                }
                catch (TaskCanceledException)
                {

                    
                }catch (Exception ex)
                {
                    throw ex;
                }

            }
        }

        // Method to stop monitoring the file
        public void Stop()
        {
            int waitSec = 500;
            tokenhandle.Cannel(waitSec);
            Thread.Sleep(waitSec);
        }

        // Method to clear the file's content
        public void Clear()
        {
            if (File.Exists(WatchPath))
            {
                // Truncate the file to 0 bytes
                File.WriteAllText(WatchPath, string.Empty);
                _lastPosition = 0; // Reset position to the beginning
            }
        }
    }
}
